home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / BasicSplitPaneUI.java < prev    next >
Text File  |  1998-06-30  |  39KB  |  1,303 lines

  1. /*
  2.  * @(#)BasicSplitPaneUI.java    1.29 98/04/08
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.plaf.basic;
  22.  
  23. import com.sun.java.swing.*;
  24. import com.sun.java.swing.border.Border;
  25. import com.sun.java.swing.event.*;
  26. import java.awt.*;
  27. import java.awt.event.*;
  28. import java.awt.peer.ComponentPeer;
  29. import java.beans.*;
  30. import java.util.*;
  31. import java.io.Serializable;
  32. import com.sun.java.swing.plaf.SplitPaneUI;
  33. import com.sun.java.swing.plaf.ComponentUI;
  34.  
  35. /**
  36.  * Standard split pane.
  37.  * <p>
  38.  * Warning: serialized objects of this class will not be compatible with
  39.  * future swing releases.  The current serialization support is appropriate
  40.  * for short term storage or RMI between Swing1.0 applications.  It will
  41.  * not be possible to load serialized Swing1.0 objects with future releases
  42.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  43.  * baseline for the serialized form of Swing objects.
  44.  *
  45.  * @version 1.29 04/08/98
  46.  * @author Scott Violet
  47.  * @author Steve Wilson
  48.  */
  49. public class BasicSplitPaneUI extends SplitPaneUI implements
  50.        PropertyChangeListener, Serializable
  51. {
  52.     /** The divider used for non-continuous layout is added to the split pane
  53.      * with this object. */
  54.     protected static final String NON_CONTINUOUS_DIVIDER = "nonContinuousDivider";
  55.  
  56.     /** JSplitPane instance this instance is providing the look and feel for. */
  57.     protected JSplitPane splitPane;
  58.  
  59.     /** How the views are split. */
  60.     private int orientation;
  61.  
  62.     public int getOrientation() {
  63.     return orientation;
  64.     }
  65.  
  66.     public void setOrientation(int orientation) {
  67.     this.orientation = orientation;
  68.     }
  69.  
  70.     /** LayoutManager that is created and placed into the split pane. */
  71.     protected BasicHorizontalLayoutManager layoutManager;
  72.  
  73.     /** Responsible for handling the current dragging session. */
  74.     private boolean continuousLayout;
  75.  
  76.     public boolean isContinuousLayout() {
  77.     return continuousLayout;
  78.     }
  79.     
  80.     public void setContinuousLayout(boolean b) {
  81.     continuousLayout = b;
  82.     }
  83.  
  84.     /** Divides the two views. */
  85.     protected BasicSplitPaneDivider divider;
  86.  
  87.     /** Last location the divider was at. */
  88.     private int lastDragLocation;
  89.  
  90.     public int getLastDragLocation() {
  91.     return lastDragLocation;
  92.     }
  93.  
  94.     public void setLastDragLocation(int l) {
  95.     lastDragLocation = l;
  96.     }
  97.  
  98.     /** The size of the divider while the dragging session is valid. */
  99.     protected int dividerSize;
  100.  
  101.     /** Activated during a dragging session when the */
  102.     protected Component nonContinuousLayoutDivider;
  103.  
  104.     /** Set to true in startDragging if any of the children
  105.      * (not including the nonContinuousLayoutDivider) are heavy
  106.      * weights. */
  107.     protected boolean draggingHW;
  108.  
  109.     /** Location of the divider when the dragging session began. */
  110.     protected int beginDragDividerLocation;
  111.  
  112.     /**
  113.       * Creates a new BasicSplitPaneUI instance
  114.       */
  115.     public static ComponentUI createUI(JComponent x) {
  116.     return new BasicSplitPaneUI();
  117.     }
  118.  
  119.     /**
  120.       * Creates a new instance of SplitPaneUI.
  121.       */
  122.     public BasicSplitPaneUI() {
  123.     setLastDragLocation(-1);
  124.     }
  125.  
  126.     /**
  127.       * Installs the reciever as the L&F for the passed in split pane.
  128.       */
  129.     public void installUI(JComponent c) {
  130.     installDefaults(c);
  131.     installListeners(c);
  132.     splitPane.layout();
  133.     }
  134.  
  135.     protected void installDefaults(JComponent c){ 
  136.     splitPane = (JSplitPane)c;
  137.  
  138.  
  139.  
  140.     LookAndFeel.installBorder(c, "SplitPane.border");
  141.  
  142.     if(divider == null)
  143.         divider = createDefaultDivider();
  144.     divider.setBasicSplitPaneUI(this);
  145.  
  146.     splitPane.setDividerSize( ((Integer)(UIManager.get("SplitPane.dividerSize"))).intValue()  );
  147.  
  148.            divider.setDividerSize(splitPane.getDividerSize());
  149.     splitPane.add(divider, JSplitPane.DIVIDER);
  150.  
  151.     setOrientation(splitPane.getOrientation());
  152.     setContinuousLayout(splitPane.isContinuousLayout());
  153.  
  154.     resetLayoutManager();
  155.     /* Install the nonContinuousLayoutDivider here to avoid having to
  156.        add/remove everything later. */
  157.     if(nonContinuousLayoutDivider == null) {
  158.         setNonContinuousLayoutDivider(createDefaultNonContinuousLayoutDivider(),
  159.                       true);
  160.     } else {
  161.         setNonContinuousLayoutDivider(nonContinuousLayoutDivider, true);
  162.     }
  163.     }
  164.  
  165.     protected void installListeners(JComponent c) {
  166.     splitPane.addPropertyChangeListener(this);
  167.     }
  168.  
  169.     /**
  170.       * Removes the receiver from the L&F controller of the passed in split
  171.       * pane.
  172.       */
  173.     public void uninstallUI(JComponent c) {
  174.     uninstallListeners(c);
  175.     uninstallDefaults(c);
  176.     }
  177.  
  178.     protected void uninstallListeners(JComponent c) {
  179.     splitPane.removePropertyChangeListener(this);
  180.     }
  181.  
  182.     protected void uninstallDefaults(JComponent c) {
  183.     if(splitPane.getLayout() == layoutManager) {
  184.         splitPane.setLayout(null);
  185.     }
  186.  
  187.  
  188.     if(nonContinuousLayoutDivider != null) {
  189.         splitPane.remove(nonContinuousLayoutDivider);
  190.     }
  191.  
  192.     splitPane.remove(divider);
  193.     divider.setBasicSplitPaneUI(null);
  194.     splitPane = null;
  195.     layoutManager = null;
  196.  
  197.     setNonContinuousLayoutDivider(null);
  198.     }
  199.  
  200.     /**
  201.       * Messaged from the JSplitPane the reciever is contained in.
  202.       * May potentially reset the layout manager and cause a
  203.       * validate() to be sent.
  204.       */
  205.     public void propertyChange(PropertyChangeEvent e) {
  206.     if(e.getSource() == splitPane) {
  207.         String changeName = e.getPropertyName();
  208.  
  209.         if(changeName.equals(JSplitPane.ORIENTATION_PROPERTY)) {
  210.         orientation = splitPane.getOrientation();
  211.         resetLayoutManager();
  212.         } else if(changeName.equals(JSplitPane.CONTINUOUS_LAYOUT_PROPERTY)) {
  213.         setContinuousLayout(splitPane.isContinuousLayout());
  214.         if(!isContinuousLayout()) {
  215.             if(nonContinuousLayoutDivider == null) {
  216.               setNonContinuousLayoutDivider(createDefaultNonContinuousLayoutDivider(), true);
  217.             } else if(nonContinuousLayoutDivider.getParent() == null) {
  218.               setNonContinuousLayoutDivider(
  219.               nonContinuousLayoutDivider, true);
  220.             }
  221.         }
  222.         } else if(changeName.equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) {
  223.         divider.setDividerSize(splitPane.getDividerSize());
  224.         layoutManager.resetSizeAt(2);
  225.         splitPane.invalidate();
  226.         splitPane.validate();
  227.         }
  228.     }
  229.     }
  230.  
  231.     /**
  232.       * Sets the Component used to divider the two Components.
  233.       */
  234.   // PENDING (Steve) - remove this method as unused?
  235. /*    public void setDivider(BasicSplitPaneDivider newD) {
  236.     if(newD != null) {
  237.         if(splitPane != null) {
  238.         if(divider != null) {
  239.             splitPane.remove(divider);
  240.         }
  241.         divider = newD;
  242.         splitPane.add(divider, JSplitPane.DIVIDER);
  243.         layoutManager.resetSizeAt(2);
  244.         splitPane.invalidate();
  245.         splitPane.validate();
  246.         } else {
  247.         divider = newD;
  248.         }
  249.         divider.setBasicSplitPaneUI(this);
  250.     }
  251.     }*/
  252.  
  253.     /**
  254.       * Returns the divider between the top Components.
  255.       */
  256.     public BasicSplitPaneDivider getDivider() {
  257.     return divider;
  258.     }
  259.  
  260.     /**
  261.      * Returns the default non continuous layout divider, which is an
  262.      * instanceof Canvas that fills the background in dark gray.
  263.      */
  264.     protected Component createDefaultNonContinuousLayoutDivider() {
  265.     return new Canvas() {
  266.         public void paint(Graphics g) {
  267.         if(!isContinuousLayout() && getLastDragLocation() != -1) {
  268.             Dimension      size = splitPane.getSize();
  269.  
  270.             g.setColor(Color.darkGray);
  271.             if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  272.             g.fillRect(0, 0, dividerSize - 1, size.height - 1);
  273.             } else {
  274.             g.fillRect(0, 0, size.width - 1, dividerSize - 1);
  275.             }
  276.         }
  277.         }
  278.     };
  279.     }
  280.  
  281.     /**
  282.      * Sets the divider to use when the splitPane is configured to
  283.      * not continuously layout. This divider will only be used during a
  284.      * dragging session. It is recommended that the passed in component
  285.      * be a heavy weight.
  286.      */
  287.     protected void setNonContinuousLayoutDivider(Component newDivider) {
  288.     setNonContinuousLayoutDivider(newDivider, true);
  289.     }
  290.  
  291.     protected void setNonContinuousLayoutDivider(Component newDivider,
  292.                          boolean rememberSizes) {
  293.     if(nonContinuousLayoutDivider != null && splitPane != null) {
  294.         splitPane.remove(nonContinuousLayoutDivider);
  295.     }
  296.     nonContinuousLayoutDivider = newDivider;
  297.     if(nonContinuousLayoutDivider != null && splitPane != null) {
  298.         nonContinuousLayoutDivider.setLocation(-1000, -1000);
  299.  
  300.         /* Needs to remove all the components and readd them!
  301.            YECK! */
  302.         Component             leftC = splitPane.getLeftComponent();
  303.         Component             rightC = splitPane.getRightComponent();
  304.         int[]                 sizes = layoutManager.getSizes();
  305.  
  306.         if(leftC != null)
  307.         splitPane.setLeftComponent(null);
  308.         if(rightC != null)
  309.         splitPane.setRightComponent(null);
  310.         splitPane.remove(divider);
  311.         splitPane.add(nonContinuousLayoutDivider, BasicSplitPaneUI.
  312.               NON_CONTINUOUS_DIVIDER,
  313.               splitPane.getComponentCount());
  314.         splitPane.setLeftComponent(leftC);
  315.         splitPane.setRightComponent(rightC);
  316.         splitPane.add(divider, JSplitPane.DIVIDER);
  317.         if(rememberSizes)
  318.         layoutManager.setSizes(sizes);
  319.         splitPane.validate();
  320.         splitPane.paintImmediately(splitPane.getX(),
  321.                        splitPane.getY(),
  322.                        splitPane.getWidth(),
  323.                        splitPane.getHeight());
  324.     }
  325.     }
  326.  
  327.     /**
  328.      * Returns the divider to use when the splitPane is configured to
  329.      * not continuously layout. This divider will only be used during a
  330.      * dragging session.
  331.      */
  332.     public Component getNonContinuousLayoutDivider() {
  333.     return nonContinuousLayoutDivider;
  334.     }
  335.  
  336.     /**
  337.       * Returns the splitpane this instance is currently contained
  338.       * in.
  339.       */
  340.     public JSplitPane getSplitPane() {
  341.     return splitPane;
  342.     }
  343.  
  344.     /**
  345.       * Creates the default divider.
  346.       */
  347.     public BasicSplitPaneDivider createDefaultDivider() {
  348.     return new BasicSplitPaneDivider(this);
  349.     }
  350.  
  351.     /**
  352.       * Messaged to reset the preferred sizes.
  353.       */
  354.     public void resetToPreferredSizes() {
  355.     if(splitPane != null) {
  356.         layoutManager.resetToPreferredSizes();
  357.         //        splitPane.invalidate();
  358.         splitPane.validate();
  359.         layoutManager.layoutContainer(splitPane);
  360.     }
  361.     }
  362.  
  363.     /**
  364.       * Sets the location of the divider to location.
  365.       */
  366.     public void setDividerLocation(int location) {
  367.  
  368.     Component                 leftC = splitPane.getLeftComponent();
  369.     Component                 rightC = splitPane.getRightComponent();
  370.  
  371.     if(leftC != null && rightC != null) {
  372.         Insets                insets = splitPane.getInsets();
  373.  
  374.         if(insets != null) {
  375.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  376.             leftC.setSize(Math.max(0, location - insets.left), 10);
  377.         } else {
  378.             leftC.setSize(10, Math.max(0, location - insets.top));
  379.         }
  380.         } else {
  381.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  382.             leftC.setSize(Math.max(0, location), 10);
  383.         } else {
  384.             leftC.setSize(10, Math.max(0, location));
  385.         }
  386.         }
  387.         //        splitPane.invalidate();
  388.         splitPane.validate();
  389.         splitPane.repaint();
  390.     }
  391.     }
  392.  
  393.     /**
  394.       * Returns the location of the divider.
  395.       */
  396.     public int getDividerLocation() {
  397.     if(orientation == JSplitPane.HORIZONTAL_SPLIT)
  398.         return divider.getLocation().x;
  399.     return divider.getLocation().y;
  400.     }
  401.  
  402.     /**
  403.       * Gets the minimum location of the divider.
  404.       */
  405.     public int getMinimumDividerLocation() {
  406.     int       minLoc = 0;
  407.     Component leftC = splitPane.getLeftComponent();
  408.     if (leftC != null) {
  409.         Insets    insets = splitPane.getInsets();
  410.             Dimension minSize = leftC.getMinimumSize();
  411.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  412.         minLoc = minSize.width;
  413.         } else {
  414.         minLoc = minSize.height;
  415.         }
  416.         minLoc += getDividerBorderSize();
  417.         if(insets != null) {
  418.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  419.             minLoc += insets.left;
  420.         } else {
  421.             minLoc += insets.top;
  422.         }
  423.         }
  424.     }
  425.     return minLoc;
  426.     }
  427.  
  428.     /**
  429.       * Gets the maximum location of the divider.
  430.       */
  431.     public int getMaximumDividerLocation() {
  432.     Dimension splitPaneSize = splitPane.getSize();
  433.     int       maxLoc = 0;
  434.     Component rightC = splitPane.getRightComponent();
  435.     if (rightC != null) {
  436.         Insets    insets = splitPane.getInsets();
  437.             Dimension minSize = rightC.getMinimumSize();
  438.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  439.         maxLoc = splitPaneSize.width - minSize.width;
  440.         } else {
  441.         maxLoc = splitPaneSize.height - minSize.height; 
  442.         }
  443.         maxLoc -= (dividerSize + getDividerBorderSize());
  444.         if(insets != null) {
  445.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  446.             maxLoc += insets.left;
  447.         } else {
  448.             maxLoc += insets.top;
  449.         }
  450.         }
  451.     }
  452.     return Math.max(getMinimumDividerLocation(), maxLoc);
  453.     }
  454.  
  455.     /**
  456.      * Messaged after the JSplitPane the receiver is providing the look
  457.      * and feel for paints its children.
  458.      */
  459.     public void finishedPaintingChildren(JSplitPane jc, Graphics g) {
  460.     if(jc == splitPane && getLastDragLocation() != -1 &&
  461.         !isContinuousLayout() && !draggingHW) {
  462.         Dimension      size = splitPane.getSize();
  463.  
  464.         g.setColor(Color.darkGray);
  465.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  466.         g.fillRect(getLastDragLocation(), 0, dividerSize - 1, size.height - 1);
  467.         } else {
  468.         g.fillRect(0, lastDragLocation, size.width - 1, dividerSize - 1);
  469.         }
  470.     }
  471.     }
  472.  
  473.     /**
  474.       * Messaged to paint the look and feel.
  475.       */
  476.     public void paint(Graphics g, JComponent jc) {
  477.     }
  478.  
  479.     /**
  480.       * Returns the preferred size for the passed in component,
  481.       * This is passed off to the current layoutmanager.
  482.       */
  483.     public Dimension getPreferredSize(JComponent jc) {
  484.     if(splitPane != null)
  485.         return layoutManager.preferredLayoutSize(splitPane);
  486.     return new Dimension(0, 0);
  487.     }
  488.  
  489.     /**
  490.       * Returns the minimum size for the passed in component,
  491.       * This is passed off to the current layoutmanager.
  492.       */
  493.     public Dimension getMinimumSize(JComponent jc) {
  494.     if(splitPane != null)
  495.         return layoutManager.minimumLayoutSize(splitPane);
  496.     return new Dimension(0, 0);
  497.     }
  498.  
  499.     /**
  500.       * Returns the maximum size for the passed in component,
  501.       * This is passed off to the current layoutmanager.
  502.       */
  503.     public Dimension getMaximumSize(JComponent jc) {
  504.     if(splitPane != null)
  505.         return layoutManager.maximumLayoutSize(splitPane);
  506.     return new Dimension(0, 0);
  507.     }
  508.  
  509.     /**
  510.      * Returns the insets. The insets are returned from the broder insets
  511.      * of the current border.
  512.      */
  513.     public Insets getInsets(JComponent jc) {
  514.     return null;
  515.     }
  516.  
  517.     /**
  518.       * Resets the layout manager based on orientation and messages it
  519.       * with invalidateLayout to pull in appropriate Components.
  520.       */
  521.     protected void resetLayoutManager() {
  522.     if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  523.         layoutManager = new BasicHorizontalLayoutManager();
  524.     } else {
  525.         layoutManager = new BasicVerticalLayoutManager();
  526.     }
  527.     splitPane.setLayout(layoutManager);
  528.     layoutManager.updateComponents();
  529.            splitPane.validate();
  530.     splitPane.repaint();
  531.     }
  532.  
  533.     /**
  534.       * Should be messaged before the dragging session starts, resets
  535.       * lastDragLocation and dividerSize.
  536.       */
  537.     protected void startDragging() {
  538.     Component                 leftC = splitPane.getLeftComponent();
  539.     Component                 rightC = splitPane.getRightComponent();
  540.     ComponentPeer             cPeer;
  541.  
  542.     beginDragDividerLocation = getDividerLocation();
  543.     draggingHW = false;
  544.     if(leftC != null && (cPeer = leftC.getPeer()) != null &&
  545.        !(cPeer instanceof java.awt.peer.LightweightPeer)) {
  546.         draggingHW = true;
  547.     } else if(rightC != null && (cPeer = rightC.getPeer()) != null
  548.           && !(cPeer instanceof java.awt.peer.LightweightPeer)) {
  549.         draggingHW = true;
  550.     }
  551.     if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  552.         setLastDragLocation(divider.getBounds().x);
  553.         dividerSize = divider.getSize().width + 2 * getDividerBorderSize();
  554.         if(!isContinuousLayout() && draggingHW) {
  555.         nonContinuousLayoutDivider.setBounds
  556.             (getLastDragLocation(), 0, dividerSize, splitPane.getHeight());
  557.         }
  558.     } else {
  559.         setLastDragLocation(divider.getBounds().y);
  560.         dividerSize = divider.getSize().height + 2 *
  561.         getDividerBorderSize();
  562.         if(!isContinuousLayout() && draggingHW) {
  563.         nonContinuousLayoutDivider.setBounds
  564.             (0, getLastDragLocation(), splitPane.getWidth(), dividerSize);
  565.         }
  566.     }
  567.     }
  568.  
  569.     /**
  570.       * Messaged during a dragging session to move the divider to the
  571.       * passed in location. If continuousLayout is true the location is
  572.       * reset and the splitPane validated.
  573.       */
  574.     protected void dragDividerTo(int location) {
  575.     if(getLastDragLocation() != location) {
  576.         if(isContinuousLayout()) {
  577.         Component          leftC = splitPane.getLeftComponent();
  578.         Rectangle          leftBounds = leftC.getBounds();
  579.  
  580.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  581.             leftC.setSize(location - leftBounds.x,
  582.                   leftBounds.height);
  583.         } else {
  584.             leftC.setSize(leftBounds.width, location - leftBounds.y);
  585.         }
  586.         splitPane.validate();
  587.         splitPane.repaint();
  588.         setLastDragLocation(location);
  589.         } else {
  590.         int lastLoc = getLastDragLocation();
  591.  
  592.         setLastDragLocation(location);
  593.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  594.             int      splitHeight = splitPane.getSize().height;
  595.  
  596.             if(draggingHW) {
  597.             nonContinuousLayoutDivider.setLocation(getLastDragLocation(),0);
  598.             } else {
  599.             splitPane.repaint(lastLoc, 0, dividerSize, splitHeight);
  600.             splitPane.repaint(location, 0, dividerSize, splitHeight);
  601.             }
  602.         } else {
  603.             int      splitWidth = splitPane.getSize().width;
  604.  
  605.             if(draggingHW) {
  606.             nonContinuousLayoutDivider.setLocation(0, getLastDragLocation());
  607.             } else {
  608.               splitPane.repaint(0, lastLoc, splitWidth, dividerSize);
  609.               splitPane.repaint(0, location, splitWidth, dividerSize);
  610.             }
  611.         }
  612.         }
  613.     }
  614.     }
  615.  
  616.     /**
  617.       * Messaged to finish the dragging session. If not continuous display
  618.       * the dividers location will be reset.
  619.       */
  620.     protected void finishDraggingTo(int location) {
  621.     dragDividerTo(location);
  622.     setLastDragLocation(-1);
  623.     if(!isContinuousLayout()) {
  624.         Component          leftC = splitPane.getLeftComponent();
  625.         Rectangle          leftBounds = leftC.getBounds();
  626.  
  627.         if(orientation == JSplitPane.HORIZONTAL_SPLIT) {
  628.         int      splitHeight = splitPane.getSize().height;
  629.  
  630.         leftC.setSize(location - leftBounds.x,
  631.                   leftBounds.height);
  632.         if(draggingHW)
  633.             nonContinuousLayoutDivider.setLocation(-dividerSize, 0);
  634.         splitPane.paintImmediately(location, 0, dividerSize,
  635.                        splitHeight);
  636.         } else {
  637.         int      splitWidth = splitPane.getSize().width;
  638.  
  639.         leftC.setSize(leftBounds.width, location - leftBounds.y);
  640.         if(draggingHW)
  641.             nonContinuousLayoutDivider.setLocation(0, -dividerSize);
  642.         splitPane.paintImmediately(0, location, splitWidth,
  643.                        dividerSize);
  644.         }
  645.         /* Do the layout. */
  646.         splitPane.validate();
  647.         splitPane.repaint();
  648.     }
  649.     splitPane.setLastDividerLocation(beginDragDividerLocation);
  650.     }
  651.  
  652.     /**
  653.      * Returns the width of one side of the divider border.
  654.      */
  655.     protected int getDividerBorderSize() {
  656.     return 1;
  657.     }
  658.  
  659.  
  660.     /**
  661.      * LayoutManager for JSplitPanes that have an orientation of
  662.      * HORIZONTAL_SPLIT.
  663.      * <p>
  664.      * Warning: serialized objects of this class will not be compatible with
  665.      * future swing releases.  The current serialization support is appropriate
  666.      * for short term storage or RMI between Swing1.0 applications.  It will
  667.      * not be possible to load serialized Swing1.0 objects with future releases
  668.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  669.      * baseline for the serialized form of Swing objects.
  670.       */
  671.     public class BasicHorizontalLayoutManager extends Object implements
  672.           LayoutManager2, Serializable
  673.     {
  674.     /* left, right, divider. */
  675.     protected int[]                   sizes;
  676.     protected Component[]             components;
  677.     protected int                     dividerLocation;
  678.  
  679.  
  680.     BasicHorizontalLayoutManager() {
  681.         components = new Component[3];
  682.         components[0] = components[1] = components[2] = null;
  683.         sizes = new int[3];
  684.         dividerLocation = -1;
  685.     }
  686.  
  687.     /**
  688.      * Resets the size of the Component at the passed in location.
  689.      */
  690.     protected void resetSizeAt(int index) {
  691.         sizes[index] = -1;
  692.     }
  693.  
  694.     /**
  695.      * Sets the sizes to <code>newSizes</code>.
  696.      */
  697.     protected void setSizes(int[] newSizes) {
  698.         System.arraycopy(newSizes, 0, sizes, 0, 3);
  699.     }
  700.  
  701.     /**
  702.      * Returns the sizes of the components.
  703.      */
  704.     protected int[] getSizes() {
  705.         int[]         retSizes = new int[3];
  706.  
  707.         System.arraycopy(sizes, 0, retSizes, 0, 3);
  708.         return retSizes;
  709.     }
  710.  
  711.     /**
  712.       * Returns the width of the passed in Components preferred size.
  713.       */
  714.     protected int getPreferredSizeOfComponent(Component c) {
  715.         return c.getPreferredSize().width;
  716.     }
  717.  
  718.     /**
  719.       * Returns the width of the passed in component.
  720.       */
  721.     protected int getSizeOfComponent(Component c) {
  722.         return c.getSize().width;
  723.     }
  724.  
  725.     /**
  726.       * Returns the available width based on the container size and
  727.       * Insets.
  728.       */
  729.     protected int getAvailableSize(Dimension containerSize,
  730.                        Insets insets) {
  731.         if(insets == null)
  732.         return containerSize.width;
  733.         return (containerSize.width - (insets.left + insets.right + 2 *
  734.                           getDividerBorderSize()));
  735.     }
  736.  
  737.     /**
  738.       * Returns the left inset, unless the Insets or null in which case
  739.       * 0 is returned.
  740.       */
  741.     protected int getInitialLocation(Insets insets) {
  742.         if(insets != null)
  743.         return insets.left;
  744.         return 0;
  745.     }
  746.  
  747.     /**
  748.       * Sets the width of the component c to be c, placing its
  749.       * x location at location, y to the insets.top and height
  750.       * to the containersize.height less the top and bottom insets.
  751.       */
  752.     protected void setComponentToSize(Component c, int size,
  753.                       int location, Insets insets,
  754.                       Dimension containerSize) {
  755.         if(insets != null) {
  756.         c.setBounds(location, insets.top, size, containerSize.height -
  757.                 (insets.top + insets.bottom));
  758.         } else {
  759.         c.setBounds(location, 0, size, containerSize.height);
  760.         }
  761.     }
  762.  
  763.     public void layoutContainer(Container container) {
  764.  
  765.  
  766.         Dimension         containerSize = container.getSize();
  767.         // if the splitpane has a zero size then no op out of here.
  768.         // if we execute this function now, we're going to cause ourselves
  769.         // much grief.
  770.         if (containerSize.height == 0 || containerSize.width == 0 ) {
  771.             return;
  772.         }
  773.  
  774.         int               counter;
  775.         int               newSize;
  776.         int               totalSize = 0;
  777.  
  778.  
  779.         Insets            insets = splitPane.getInsets();
  780.         int               availableSize = getAvailableSize(containerSize,
  781.                                    insets);
  782.         int               beginLocation;
  783.  
  784.         /* Set the last location. */
  785.         beginLocation = splitPane.getDividerLocation();
  786.  
  787.         /* Check to see if the size of something has changed and
  788.            adjust the other Component if it has. */
  789.         for(counter = 0; counter < 3; counter++) {
  790.         if(components[counter] != null) {
  791.             /* -1 signifies this is the first time this component
  792.                is being layed out and that the preferred size should
  793.                be asked for. */
  794.             if(sizes[counter] == -1) {
  795.             sizes[counter] = Math.min(availableSize,
  796.                  getPreferredSizeOfComponent(components[counter]));
  797.             } else {
  798.             newSize = getSizeOfComponent(components[counter]);
  799.             if(sizes[counter] != newSize) {
  800.                 if(counter == 0) {
  801.                 if(components[1] != null) {
  802.                     sizes[1] = Math.max(0, sizes[1] +
  803.                         (sizes[counter] - newSize));
  804.                 }
  805.                 } else if(counter == 1) {
  806.                 if(components[0] != null) {
  807.                     sizes[0] = Math.max(0, sizes[0] +
  808.                         (sizes[counter] - newSize));
  809.                 }
  810.                 }
  811.                 sizes[counter] = newSize;
  812.                 /* Do this to not adjust the next one, but adjust
  813.                    the divider. */
  814.                 if(counter == 0)
  815.                 counter = 1;
  816.             }
  817.             }
  818.         }
  819.         }
  820.  
  821.         for(counter = 0; counter < 3; counter++)
  822.         totalSize += sizes[counter];
  823.  
  824.         /* If the width has changed, adjust the right, and then left
  825.            component (if necessary). */
  826.         if(totalSize != availableSize) {
  827.         int           toDiff = (availableSize - totalSize);
  828.  
  829.         if(components[1] != null) {
  830.             newSize = Math.max(0, sizes[1] + toDiff);
  831.             if(newSize == 0) {
  832.             toDiff += sizes[1];
  833.             sizes[1] = 0;
  834.             if(components[0] != null)
  835.                 sizes[0] = Math.max(0, sizes[0] + toDiff);
  836.             } else {
  837.             sizes[1] = newSize;
  838.             }
  839.         } else if(components[0] != null) {
  840.             sizes[0] = Math.max(0, sizes[0] + toDiff);
  841.         }
  842.         }
  843.  
  844.         /* Reset the bounds of each component. */
  845.         int                  nextLocation = getInitialLocation(insets);
  846.         int                  bdSize = getDividerBorderSize();
  847.  
  848.         counter = 0;
  849.         while(counter < 3) {
  850.         if(components[counter] != null) {
  851.             setComponentToSize(components[counter], sizes[counter],
  852.                        nextLocation, insets, containerSize);
  853.             nextLocation += sizes[counter];
  854.         }
  855.         switch(counter) {
  856.         case 0:
  857.             counter = 2;
  858.             nextLocation += bdSize;
  859.             break;
  860.         case 2:
  861.             counter = 1;
  862.             nextLocation += bdSize;
  863.             break;
  864.         case 1:
  865.             counter = 3;
  866.             break;
  867.         }
  868.         }
  869.  
  870.         if(beginLocation != splitPane.getDividerLocation()) {
  871.         splitPane.setLastDividerLocation(beginLocation);
  872.         }
  873.  
  874.     }
  875.  
  876.     /**
  877.       * Adds the component at place.  Place must be one of
  878.       * JSplitPane.LEFT, RIGHT, TOP, BOTTOM, or null (for the
  879.       * divider).
  880.       */
  881.     public void addLayoutComponent(String place, Component component) {
  882.         boolean         isValid = true;
  883.  
  884.         if(place != null) {
  885.         if(place.equals(JSplitPane.DIVIDER)) {
  886.             /* Divider. */
  887.             components[2] = component;
  888.             sizes[2] = -1;
  889.         } else if(place.equals(JSplitPane.LEFT) ||
  890.             place.equals(JSplitPane.TOP)) {
  891.             components[0] = component;
  892.             sizes[0] = -1;
  893.         } else if(place.equals(JSplitPane.RIGHT) ||
  894.             place.equals(JSplitPane.BOTTOM)) {
  895.             components[1] = component;
  896.             sizes[1] = -1;
  897.         } else if(!place.equals(BasicSplitPaneUI.NON_CONTINUOUS_DIVIDER))
  898.             isValid = false;
  899.         } else {
  900.         isValid = false;
  901.         }
  902.         if(!isValid)
  903.         throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + place);
  904.     }
  905.  
  906.     /**
  907.       * Returns the minimum size needed to contain the children.
  908.       * The width is the sum of all the childrens min widths and
  909.       * the height is the largest of the childrens minimum heights.
  910.       */
  911.     public Dimension minimumLayoutSize(Container container) {
  912.         Dimension              minSize;
  913.         int                    minX, minY;
  914.         Insets                 insets = splitPane.getInsets();
  915.  
  916.         minX = minY = 0;
  917.  
  918.         for(int counter = 0; counter < 3; counter++) {
  919.         if(components[counter] != null) {
  920.             minSize = components[counter].getMinimumSize();
  921.             minX += minSize.width;
  922.             if(minSize.height > minY)
  923.             minY = minSize.height;
  924.         }
  925.         }
  926.         if(insets != null) {
  927.         minX += insets.left + insets.right;
  928.         minY += insets.bottom + insets.top;
  929.         }
  930.         return new Dimension(minX, minY);
  931.     }
  932.  
  933.     /**
  934.       * Returns the preferred size needed to contain the children.
  935.       * The width is the sum of all the childrens preferred widths and
  936.       * the height is the largest of the childrens preferred heights.
  937.       */
  938.     public Dimension preferredLayoutSize(Container container) {
  939.         Dimension              preSize;
  940.         int                    preX, preY;
  941.         Insets                 insets = splitPane.getInsets();
  942.  
  943.         preX = preY = 0;
  944.  
  945.         for(int counter = 0; counter < 3; counter++) {
  946.         if(components[counter] != null) {
  947.             preSize = components[counter].getPreferredSize();
  948.             preX += preSize.width;
  949.             if(preSize.height > preY)
  950.             preY = preSize.height;
  951.         }
  952.         }
  953.         if(insets != null) {
  954.         preX += insets.left + insets.right;
  955.         preY += insets.bottom + insets.top;
  956.         }
  957.         return new Dimension(preX, preY);
  958.     }
  959.  
  960.     /**
  961.       * Removes the specified component from our knowledge.
  962.       */
  963.     public void removeLayoutComponent(Component component) {
  964.         for(int counter = 0; counter < 3; counter++) {
  965.         if(components[counter] == component) {
  966.             components[counter] = null;
  967.             sizes[counter] = 0;
  968.         }
  969.         }
  970.     }
  971.  
  972.     //
  973.     // LayoutManager2
  974.     //
  975.     /**
  976.       * Adds the specified component to the layout, using the specified
  977.       * constraint object.
  978.       * @param comp the component to be added
  979.       * @param constraints  where/how the component is added to the layout.
  980.       */
  981.     public void addLayoutComponent(Component comp, Object constraints) {
  982.         if ((constraints == null) || (constraints instanceof String)) {
  983.         addLayoutComponent((String)constraints, comp);
  984.         } else {
  985.         throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)");
  986.         }
  987.     }
  988.  
  989.     /**
  990.       * Returns the alignment along the x axis.  This specifies how
  991.       * the component would like to be aligned relative to other 
  992.       * components.  The value should be a number between 0 and 1
  993.       * where 0 represents alignment along the origin, 1 is aligned
  994.       * the furthest away from the origin, 0.5 is centered, etc.
  995.       */
  996.     public float getLayoutAlignmentX(Container target) {
  997.         return 0.0f;
  998.     }
  999.  
  1000.     /**
  1001.       * Returns the alignment along the y axis.  This specifies how
  1002.       * the component would like to be aligned relative to other 
  1003.       * components.  The value should be a number between 0 and 1
  1004.       * where 0 represents alignment along the origin, 1 is aligned
  1005.       * the furthest away from the origin, 0.5 is centered, etc.
  1006.       */
  1007.     public float getLayoutAlignmentY(Container target) {
  1008.         return 0.0f;
  1009.     }
  1010.  
  1011.     /**
  1012.       * Does nothing. If the developer really wants to change the
  1013.       * size of one of the views JSplitPane.resetToPreferredSizes should
  1014.       * be messaged.
  1015.       */
  1016.     public void invalidateLayout(Container c) {
  1017.     }
  1018.  
  1019.     /**
  1020.       * Returns the maximum layout size, which is Integer.MAX_VALUE
  1021.       * in both directions.
  1022.       */
  1023.     public Dimension maximumLayoutSize(Container target) {
  1024.         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  1025.     }
  1026.  
  1027.     /**
  1028.       * Resets the cached sizes so that next time this instance is
  1029.       * layed out it'll ask for the preferred sizes.
  1030.       */
  1031.     public void resetToPreferredSizes() {
  1032.         for(int counter = 0; counter < 3; counter++)
  1033.         sizes[counter] = -1;
  1034.     }
  1035.  
  1036.     /**
  1037.       * Determines the components. This should be called whenever
  1038.       * a new instance of this is installed into an existing
  1039.       * SplitPane.
  1040.       */
  1041.     protected void updateComponents() {
  1042.         Component              comp;
  1043.  
  1044.         comp = splitPane.getLeftComponent();
  1045.         if(components[0] != comp) {
  1046.         components[0] = comp;
  1047.         if(comp == null) {
  1048.             sizes[0] = 0;
  1049.         } else {
  1050.             sizes[0] = -1;
  1051.         }
  1052.         }
  1053.  
  1054.         comp = splitPane.getRightComponent();
  1055.         if(components[1] != comp) {
  1056.         components[1] = comp;
  1057.         if(comp == null) {
  1058.             sizes[1] = 0;
  1059.         } else {
  1060.             sizes[1] = -1;
  1061.         }
  1062.         }
  1063.  
  1064.         /* Find the divider. */
  1065.         Component[]           children = splitPane.getComponents();
  1066.         Component             oldDivider = components[2];
  1067.  
  1068.         components[2] = null;
  1069.         for(int counter = children.length - 1; counter >= 0; counter--) {
  1070.         if(children[counter] != components[0] &&
  1071.            children[counter] != components[1] &&
  1072.             children[counter] != nonContinuousLayoutDivider) {
  1073.             if(oldDivider != children[counter]) {
  1074.             components[2] = children[counter];
  1075.             if(children[counter] == null) {
  1076.                 sizes[2] = 0;
  1077.             } else {
  1078.                 sizes[2] = -1;
  1079.             }
  1080.             } else {
  1081.             components[2] = oldDivider;
  1082.             }
  1083.             break;
  1084.         }
  1085.         }
  1086.         if(components[2] == null)
  1087.         sizes[2] = 0;
  1088.     }
  1089.     } // End of class BasicSplitPaneUI.BasicHorizontalLayoutManager
  1090.  
  1091.  
  1092.     /**
  1093.      * LayoutManager used for JSplitPanes with an orientation of
  1094.      * VERTICAL_SPLIT.
  1095.      * <p>
  1096.      * Warning: serialized objects of this class will not be compatible with
  1097.      * future swing releases.  The current serialization support is appropriate
  1098.      * for short term storage or RMI between Swing1.0 applications.  It will
  1099.      * not be possible to load serialized Swing1.0 objects with future releases
  1100.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1101.      * baseline for the serialized form of Swing objects.
  1102.      */
  1103.     public class BasicVerticalLayoutManager extends
  1104.             BasicHorizontalLayoutManager implements Serializable
  1105.     {
  1106.     /**
  1107.       * Returns the width of the passed in Components preferred size.
  1108.       */
  1109.     protected int getPreferredSizeOfComponent(Component c) {
  1110.         return c.getPreferredSize().height;
  1111.     }
  1112.  
  1113.     /**
  1114.       * Returns the width of the passed in component.
  1115.       */
  1116.     protected int getSizeOfComponent(Component c) {
  1117.         return c.getSize().height;
  1118.     }
  1119.  
  1120.     /**
  1121.       * Returns the available width based on the container size and
  1122.       * Insets.
  1123.       */
  1124.     protected int getAvailableSize(Dimension containerSize,
  1125.                        Insets insets) {
  1126.         if(insets == null)
  1127.         return containerSize.height;
  1128.         return (containerSize.height - (insets.bottom + insets.top + 2 *
  1129.                            getDividerBorderSize()));
  1130.     }
  1131.  
  1132.     /**
  1133.       * Returns the left inset, unless the Insets or null in which case
  1134.       * 0 is returned.
  1135.       */
  1136.     protected int getInitialLocation(Insets insets) {
  1137.         if(insets != null)
  1138.         return insets.top;
  1139.         return 0;
  1140.     }
  1141.  
  1142.     /**
  1143.       * Sets the width of the component c to be c, placing its
  1144.       * x location at location, y to the insets.top and height
  1145.       * to the containersize.height less the top and bottom insets.
  1146.       */
  1147.     protected void setComponentToSize(Component c, int size,
  1148.                       int location, Insets insets,
  1149.                       Dimension containerSize) {
  1150.         if(insets != null) {
  1151.         c.setBounds(insets.left, location, containerSize.width -
  1152.             (insets.left + insets.right), size);
  1153.         } else {
  1154.         c.setBounds(0, location, containerSize.width, size);
  1155.         }
  1156.     }
  1157.  
  1158.     /**
  1159.       * Returns the minimum size needed to contain the children.
  1160.       * The height is the sum of all the childrens min heights and
  1161.       * the width is the largest of the childrens minimum widths.
  1162.       */
  1163.     public Dimension minimumLayoutSize(Container container) {
  1164.         Dimension              minSize;
  1165.         int                    minX, minY;
  1166.         Insets                 insets = splitPane.getInsets();
  1167.  
  1168.         minX = minY = 0;
  1169.  
  1170.         for(int counter = 0; counter < 3; counter++) {
  1171.         if(components[counter] != null) {
  1172.             minSize = components[counter].getMinimumSize();
  1173.             minY += minSize.height;
  1174.             if(minSize.width > minX)
  1175.             minX = minSize.width;
  1176.         }
  1177.         }
  1178.         if(insets != null) {
  1179.         minX += insets.left + insets.right;
  1180.         minY += insets.bottom + insets.top;
  1181.         }
  1182.         return new Dimension(minX, minY);
  1183.     }
  1184.  
  1185.     /**
  1186.       * Returns the preferred size needed to contain the children.
  1187.       * The width is the sum of all the childrens preferred widths and
  1188.       * the height is the largest of the childrens preferred heights.
  1189.       */
  1190.     public Dimension preferredLayoutSize(Container container) {
  1191.         Dimension              preSize;
  1192.         int                    preX, preY;
  1193.         Insets                 insets = splitPane.getInsets();
  1194.  
  1195.         preX = preY = 0;
  1196.         for(int counter = 0; counter < 3; counter++) {
  1197.         if(components[counter] != null) {
  1198.             preSize = components[counter].getPreferredSize();
  1199.             preY += preSize.height;
  1200.             if(preSize.width > preX)
  1201.             preX = preSize.width;
  1202.         }
  1203.         }
  1204.         if(insets != null) {
  1205.         preX += insets.left + insets.right;
  1206.         preY += insets.bottom + insets.top;
  1207.         }
  1208.         return new Dimension(preX, preY);
  1209.     }
  1210.  
  1211.     } // End of class BasicSplitPaneUI.BasicHorizontalLayoutManager
  1212.  
  1213.     /**
  1214.      * This border draws the borders around both of the contained components in the
  1215.      * the splitter.  It is a very odd border.
  1216.      * <p>
  1217.      * Warning: serialized objects of this class will not be compatible with
  1218.      * future swing releases.  The current serialization support is appropriate
  1219.      * for short term storage or RMI between Swing1.0 applications.  It will
  1220.      * not be possible to load serialized Swing1.0 objects with future releases
  1221.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1222.      * baseline for the serialized form of Swing objects.
  1223.      */
  1224.     public static class SplitBorder implements Border, Serializable
  1225.     {
  1226.         private Color highlightColor;
  1227.         private Color shadowColor;
  1228.  
  1229.         public SplitBorder(Color highlight, Color shadow) {
  1230.         highlightColor = highlight;
  1231.         shadowColor = shadow;
  1232.     }
  1233.  
  1234.     public void paintBorder(Component c, Graphics g, int x, int y,
  1235.                 int width, int height) {
  1236.         Component          child;
  1237.         Rectangle          cBounds;
  1238.  
  1239.         JSplitPane splitPane = (JSplitPane)c;
  1240.         
  1241.         child = splitPane.getLeftComponent();
  1242.         if(splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
  1243.         if(child != null) {
  1244.             cBounds = child.getBounds();
  1245.             g.setColor(shadowColor);
  1246.             g.drawLine(0, 0, cBounds.width + 1, 0);
  1247.             g.drawLine(0, 1, 0, cBounds.height + 2);
  1248.  
  1249.             g.setColor(highlightColor);
  1250.             g.drawLine(1, cBounds.height + 1, cBounds.width + 2,
  1251.                    cBounds.height + 1);
  1252.             g.drawLine(cBounds.width + 1, 1, cBounds.width + 1, cBounds.height + 2);
  1253.         }
  1254.         child = splitPane.getRightComponent();
  1255.         if(child != null) {
  1256.             cBounds = child.getBounds();
  1257.  
  1258.             int             maxX = cBounds.x + cBounds.width;
  1259.             int             maxY = cBounds.y + cBounds.height;
  1260.             
  1261.             g.setColor(shadowColor);
  1262.             g.drawLine(cBounds.x - 1, 0, maxX, 0);
  1263.             g.drawLine(cBounds.x - 1, maxY, cBounds.x, maxY);
  1264.             g.drawLine(cBounds.x - 1, 0, cBounds.x -1 , maxY);
  1265.             g.setColor(highlightColor);
  1266.             g.drawLine(cBounds.x, maxY, maxX, maxY);
  1267.             g.drawLine(maxX, 0, maxX, maxY + 1);
  1268.         }
  1269.         } else {
  1270.         if(child != null) {
  1271.             cBounds = child.getBounds();
  1272.             g.setColor(shadowColor);
  1273.             g.drawLine(0, 0, cBounds.width + 1, 0);
  1274.             g.drawLine(0, 1, 0, cBounds.height + 1);
  1275.             g.setColor(highlightColor);
  1276.             g.drawLine(1 + cBounds.width, 0, 1 + cBounds.width,
  1277.                    cBounds.height + 1);
  1278.             g.drawLine(0, cBounds.height + 1, cBounds.width, cBounds.height + 1);
  1279.         }
  1280.         child = splitPane.getRightComponent();
  1281.         if(child != null) {
  1282.             cBounds = child.getBounds();
  1283.  
  1284.             int             maxX = cBounds.x + cBounds.width;
  1285.             int             maxY = cBounds.y + cBounds.height;
  1286.             
  1287.             g.setColor(shadowColor);
  1288.             g.drawLine(0, cBounds.y - 1, 0, maxY);
  1289.             g.drawLine(maxX, cBounds.y - 1, maxX, cBounds.y);
  1290.             g.drawLine(0, cBounds.y - 1, cBounds.width, cBounds.y - 1);
  1291.             g.setColor(highlightColor);
  1292.             g.drawLine(0, maxY, cBounds.width + 1, maxY);
  1293.             g.drawLine(maxX, cBounds.y, maxX, maxY);
  1294.         }
  1295.         }
  1296.     }
  1297.     public Insets getBorderInsets(Component c) {
  1298.         return new Insets(1, 1, 1, 1);
  1299.     }
  1300.     public boolean isBorderOpaque() { return true; }
  1301.     }
  1302. }
  1303.